﻿package code {
	
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.utils.getTimer;
	
	public class MainApp extends Sprite {
		
		// Geometry:
		private var centerX:Number = stage.stageWidth/2;  // horz center of bar
		private var centerY:Number = stage.stageHeight/2; // vert center of bar
		private var center:Vertex;
		
		private var R:Number       = 150;                 // length of bar to either side of center ("radius")
		private var H:Number       = 175;                 // height from ball to support (In other words, spring length)	
		
		private var right:Number   = centerX + R;         // initial x position of ball on right
		
		private var bottom:Number  = centerY + H;         // initial y position of ball on bottom
		private var centerRight:Vertex;                   // center of right ball		
		private var bottomRight:Vertex;                   // bottom of right spring
		
		// Spring info:		
		private var rightSpring:Line;                     // spring hanging from right support
		private var K:Number       = 50;                 // spring constant for both springs
		private var D:Number       = 20;                   // dampening factor on vel
		private var Y0:Number      = centerY;             // initial positions of balls and springs
		private var Vy0:Number     = 0;                   // initial velocity
		private var X0:Number      = centerX;             // initial positions of balls and springs
		private var Vx0:Number     = 0;                   // initial velocity
		private var springLength:Number = 50;
		
		// Bar info:
		private var bar:Line;                             // bar between both springs
		// you could give the bar its own mass moment of inertia: (1/2)(M)(2R)^2|
		
		// Balls info:		
		private var rightBall:Ball;                       // ball on right
		private var M:Number       = 100;                 // each ball mass
		private var BallRad:Number = 10;                  // ball radius
		private var G:Number       = 600;                // gravity (acceleration g)
		private var w:Number       = 0;                   // initial angular velocity
		private var a:Number       = 0;                   // angular acceleration
		private var theta:Number;						  // current angle
		
		// Support info:		
		private var botSupport:Support;                   // support holding right spring
		private var supportWidth   = 50;                  // support width
		private var supportHeight  = 20;                  // support height
		
		
		// Animation info:
		private var ti:Number;                            // old time for DT (deltaT = tf-ti)/animationrate
		private var tf:Number;                            // new time for DT (deltaT = tf-ti)/animationrate
		private var ANIMATION_RATE:Number = 1000;         // milliseconds
		
		// Point to rotate about		
		public var origin:Vertex = new Vertex(50, 300);
		
		//------------------------------------------------------------------------
		// Build the main app:
		//------------------------------------------------------------------------
		public function MainApp() {
			setUpObjects();
			setUpButtons();
		}
		
		//------------------------------------------------------------------------
		// Set up Start button:
		//------------------------------------------------------------------------
		private function setUpButtons():void {
			start_btn.addEventListener(MouseEvent.MOUSE_DOWN, startSim);
		}

		//------------------------------------------------------------------------
		// Start simulation after user presses Start button:
		//------------------------------------------------------------------------
		private function startSim(e:Event):void {
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
			ti = getTimer(); // get initial time
		}
		
		//------------------------------------------------------------------------
		// Run simulation:
		//------------------------------------------------------------------------
		private function onEnterFrame(event:Event):void {
			trace(rightBall.x, rightBall.y);
			updateSystem();	
			rotateSystem();
			adjustSprings();
		}
		
		//------------------------------------------------------------------------
		// Set up all shapes and sprites:
		//------------------------------------------------------------------------
		private function setUpObjects():void {
			// Geometry:
			   centerRight = new Vertex(right,centerY);
			   bottomRight = new Vertex(right,bottom);
			   center      = new Vertex(centerX,centerY);
			   
			// supports:			   
			   botSupport = new Support(new Vertex(right-supportWidth/2,bottom),
										supportWidth,supportHeight);
			  addChild(botSupport);
			
			// springs:			   
			   rightSpring = new Line(centerRight,bottomRight,4,0x0000ff);
			   addChild(rightSpring);
			
		    // Bar:
			   bar = new Line(new Vertex(0, 0),new Vertex(0, 0),7,0x000000);
			   addChild(bar);
			   
			
			// balls:			   
			   rightBall = new Ball(BallRad,0xff0000);
			   rightBall.x = right;
			   rightBall.y = centerY;			   
			   addChild(rightBall);
			   
			// nudge system so that it had initial angle:
			   theta = 0*Math.PI/180; // 30 deg clockwise 
			   rotateSystem();         // rotate entire system
			   adjustSprings();        // "entire system" doesn't include springs
		}

		//------------------------------------------------------------------------
		// Update each ball's position:
		//------------------------------------------------------------------------
		private function updateSystem():void {
			// update time:
			tf = getTimer();
			var dt = (tf-ti)/ANIMATION_RATE;
			
			// translation of balls update:
			var cos = Math.cos(theta);			
			
			if(rightBall.y < 250 && rightBall.y > 100)
			{
				var ayR:Number =  G - (K/M)*(rightBall.y)*cos;			
				rightBall.vy += ayR*dt;
				rightBall.vy -= D+0.2;
				rightBall.y += rightBall.vy*dt;
			}
			
			else
			{				
				rightBall.y = 50;
			}
			
			// rotation of balls update:             // T = (2)(r)(cos)(dy)
			a = (K*cos/(M*R))*(rightBall.y-centerY); // T = (I=2mr^2)(alpha)
			w += a*dt;
			theta += w*dt;
			
			// set up for next time update:
			ti = tf;
		}

		//------------------------------------------------------------------------
		// Rotation balls and bar:
		//------------------------------------------------------------------------
		private function rotateSystem():void {
			
			// treat center (the pin) as origin of system:
			var tmp1:Vertex = Vertex.sub(origin,centerRight);

			// rotate right ball about center:
			var tmp2:Vertex = rotateVertex(tmp1,theta); // use current angle

			// translate right ball relative to actual position (the pin):
			var tmp3:Vertex = Vertex.add(origin,tmp2);			
			
			// update ball positions:
			rightBall.x = tmp3.x;
			rightBall.y = tmp3.y;			

			// update bar:
			bar.update(origin,tmp3);
		}
		
		//------------------------------------------------------------------------
		// Rotate a vertex:
		//------------------------------------------------------------------------
		private function rotateVertex(old:Vertex,angle:Number):Vertex {
			var sin:Number = Math.sin(angle);
			var cos:Number = Math.cos(angle);
			var Xnew:Number = cos*old.x-sin*old.y;
			var Ynew:Number = sin*old.x+cos*old.y;
			return new Vertex(Xnew,Ynew);
		}

		//------------------------------------------------------------------------
		// Adjust springs:
		//------------------------------------------------------------------------
		private function adjustSprings():void {
			
			rightSpring.update(new Vertex(rightBall.x,rightBall.y),bottomRight);
		}
	}
}
